use std::fmt;

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RawStr {
    Static(&'static str),
    Owned(String),
}

#[allow(dead_code)]
impl RawStr {
    pub fn as_str(&self) -> &str {
        match self {
            RawStr::Static(s) => s,
            RawStr::Owned(s) => s.as_ref(),
        }
    }

    pub fn is_owned(&self) -> bool {
        matches!(self, RawStr::Owned(_))
    }
}

impl fmt::Display for RawStr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl From<&'static str> for RawStr {
    fn from(s: &'static str) -> Self {
        RawStr::Static(s)
    }
}

impl From<String> for RawStr {
    fn from(s: String) -> Self {
        RawStr::Owned(s)
    }
}

#[cfg(test)]
mod test {
    use super::RawStr;

    #[test]
    fn test_raw_str() {
        let s = "this is a str";
        let raw_str_1 = RawStr::from(s);
        let raw_str_2 = RawStr::from(String::from(s));
        assert_eq!("this is a str", raw_str_1.as_str());
        assert_eq!("this is a str", raw_str_2.as_str());
        assert_eq!(raw_str_1.as_str(), raw_str_2.as_str());

        assert!(!raw_str_1.is_owned());
        assert!(raw_str_2.is_owned());
    }
}
